mam jedno pytanie odnośnie interfejsu map:
nie implementuje on interfejsu iterable, natomiast posiada widoki takie jak entrySet
, keySet
, values
, które zwracają wszystkie jego elementy w jakiejś kolejności. Na stronie Oracle napisano "The order of a map is defined as the order in which the iterators on the map's collection views return their elements.". Czy znaczy to, że te metody tworzą jakieś kolekcję po to, żeby zwrócić nam pożądane wyniki? Czym różniłby się w przeciwnym wypadku collection view od zwykłego collection?
Czy brak odwzorowania klucza przez mapę jest tym samym co odwzorowanie klucza na wartość null
?
Dlaczego w interfejsie Map
metoda get(Object key)
, w przypadku gdy klucz nie zostanie znaleziony, zwraca null, a nie rzuca wyjątek?
Warto zauważyć, że może być to mylące dla początkujących programistów Javy, którzy zamiast użyć metody containsKey(Object key)
zastosują mniej czytelny warunek: map.get(key) != null
. Ponadto, jeśli mapa nie
odwzorowuje pewnych dwóch różnych kluczy foo i bar, to wyrażenie
map.get(foo) == map.get(bar)
jest prawdziwe.
Podobne przemyślenia dotyczą również metody indexOf(int ch)
w klasie
String, która zwraca "sztuczną" wartość -1, w przypadku gdy znak nie
występuje w łańcuchu. Nieuważny programista może łatwo zapomnieć o
sprawdzeniu tego przypadku. Co więcej, na zwrócona wartość -1 może
zostać wykorzystana w wyrażeniu arytmetycznym (np. ...+1, któremu
odpowiada przejście o jeden znak w prawo). A to może doprowadzić do
niepożądanego zachowania implementowanej funkcjonalności.
Ciekawi mnie również, dlaczego metoda substring(int beginIndex, int endIndex)
w klasie String ma taką nieintuicyjną sygnaturę, zamiast substring(int beginIndex, int length)
.
Stream
class LinkedStack {
static interface Linkable {
public Linkable getNext();
public void setNext(Linkable next);
}
private Linkable head;
public void push(Linkable node) {
Objects.requireNonNull(node, "Stack element cannot be null!");
node.setNext(head);
this.head = node;
}
public Linkable pop() {
Linkable result = this.head;
if(result != null){
this.head = result.getNext();
}
return result;
}
}
class LinkableInteger implements LinkedStack.Linkable {
private int value;
private LinkedStack.Linkable next;
public LinkableInteger(int i) { this.value = i; }
public LinkedStack.Linkable getNext() { return next; }
public void setNext(LinkedStack.Linkable next) { this.next = next; }
public int getValue() { return this.value; }
}
import static java.lang.System.out;
var stack = new LinkedStack();
stack.push(new LinkableInteger(1));
var linkedInteger = (LinkableInteger) stack.pop();
out.println(linkedInteger.getValue());
stack.push(null);
Map<String,Integer> numbers = new HashMap<>();
numbers.put("jeden", 1);
numbers.put("dwa", 2);
numbers.put("trzy", 3);
for(Map.Entry<String,Integer> entry : numbers.entrySet()){
System.out.println("" + entry.getKey() + " : " + entry.getValue());
}
class BoundedArrayList {
protected Object[] array;
protected int pointer = 0;
public BoundedArrayList(int size){
array = new Object[size];
}
public boolean add(Object element){
if(pointer < array.length){
array[pointer] = element;
pointer++;
return true;
} else {
return false;
}
}
}
class BoundedArrayListWithIterator extends BoundedArrayList {
protected class ForwardIterator implements Iterator {
private int index = 0;
public boolean hasNext(){
return index < pointer;
}
public Object next(){
if(index >= pointer){
throw new NoSuchElementException();
}
Object result = array[index];
index++;
return result;
}
}
public BoundedArrayListWithIterator(int size){
super(size);
}
public Iterator forwardIterator(){
return new ForwardIterator();
}
}
class BoundedArrayListWithBackwardIterator extends BoundedArrayListWithIterator {
public class BackwardIterator implements Iterator {
private int index = pointer-1;
public boolean hasNext(){
return index >= 0;
}
public Object next(){
if(index < 0){
throw new NoSuchElementException();
}
Object result = array[index];
index--;
return result;
}
}
public BoundedArrayListWithBackwardIterator(int size){
super(size);
}
public Iterator backwardIterator(){
return new BackwardIterator();
}
}
var list = new BoundedArrayListWithBackwardIterator(10);
list.add("Ala");
list.add("ma");
list.add("kota");
Iterator iterator = list.forwardIterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
iterator = list.backwardIterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
System.out.println(list.forwardIterator());
new BoundedArrayListWithBackwardIterator.BackwardIterator();
list.add("A");
list.add("Ania");
list.add("nie");
list.add("ma");
list.add("kota");
list.add(",");
list.add("ona");
list.add("ma");
list.add("psa");
iterator = list.backwardIterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
class LocalExample {
public static interface IntHolder { int getValue(); }
public void run(){
IntHolder[] holders = new IntHolder[10];
for(int i = 0; i < 10; i++){
final int fi = i;
class MyIntHolder implements IntHolder {
public int getValue() { return fi; }
}
holders[i] = new MyIntHolder();
}
for(int i = 0; i < 10; i++){
System.out.println(holders[i].getValue());
}
}
}
new LocalExample().run();
class BoundedArrayList {
private Object[] array;
private int pointer = 0;
public Iterator backwardIterator(){
return new Iterator() {
private int index = pointer-1;
public boolean hasNext(){
return index >= 0;
}
public Object next(){
if(index < 0){
throw new NoSuchElementException();
}
Object result = array[index];
index--;
return result;
}
};
}
}
class NumberCollection {
private SortedSet<String> numbers;
public NumberCollection(){
numbers = new TreeSet<>(new Comparator<String>(){
public int compare(String a, String b){
return a.length() - b.length();
}
});
}
public boolean add(String number){
return numbers.add(number);
}
public String toString(){
return numbers.toString();
}
}
NumberCollection numbers = new NumberCollection();
numbers.add("1111");
numbers.add("1");
numbers.add("111111");
numbers.add("zz");
System.out.println(numbers);
abstract class AbstractClass {
}
AbstractClass abstractValue = new AbstractClass(){};
import java.io.*;
File dir = new File("/home/apohllo");
String[] fileList = dir.list(new FilenameFilter() {
public boolean accept(File file, String fileName){
return fileName.endsWith(".java");
}
});
for(String s : fileList){
System.out.println(s);
}
import java.io.*;
String[] fileList = new File("/home/apohllo").list((f,s) -> { return s.endsWith(".java"); });
for(String s : fileList){
System.out.println(s);
}
import java.io.*;
String[] fileList = new File("/home/apohllo").
// można pominąć słowo return
list((f,s) -> s.endsWith(".java"));
for(String s : fileList){
System.out.println(s);
}
Arrays.asList(new File("/home/apohllo").list((f,s) -> s.endsWith(".java"))).
stream().forEach(System.out::println);
Stream
i techniki funkcyjne¶Collection
został rozszerzony o metodę stream
Collection
Stream
Stream
umożliwia wykonywania metod funkcyjnych:allMatch
anyMatch
collect
concat
count
distinct
empty
filter
findAny
findFirst
flatMap
forEach
map
fliter
, map
i collect
¶import java.util.stream.*;
var numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
numbers.stream().filter(e -> e % 2 == 0).
map(e -> e.toString()).
collect(Collectors.toList());
map
¶import java.util.stream.*;
var numbers = Arrays.asList("jeden", "dwa", "trzy", "cztery");
numbers.stream().map(String::length).map(Object::toString).collect(Collectors.joining(", "));
forEach
¶var numbers = Arrays.asList("jeden", "dwa", "trzy", "cztery");
numbers.stream().forEach(System.out::println);
map
i reduce
¶var numbers = Arrays.asList("jeden", "dwa", "trzy", "cztery");
double sum = numbers.stream().map(String::length).reduce(0, (x,y) -> { return x + y; });
System.out.println(sum / numbers.size());
import java.util.function.*;
import java.util.stream.*;
public class SquareGenerator implements IntSupplier {
private int current = 1;
@Override
public synchronized int getAsInt(){
int thisResult = current * current;
current++;
return thisResult;
}
}
var squares = IntStream.generate(new SquareGenerator());
var stepThrough = squares.iterator();
for(int i = 0; i < 10; i++){
System.out.println(stepThrough.nextInt());
}
System.out.println("-----------");
for(int i = 0; i < 10; i++){
System.out.println(stepThrough.nextInt());
}
var squares = IntStream.generate(new SquareGenerator());
squares.map(e -> (int) Math.sqrt(e)).limit(20).forEach(System.out::println);
import static java.lang.System.out;
public class StringConverter {
public int convertToInt(String value) throws Exception {
return Integer.parseInt(value);
}
}
var converter = new StringConverter();
Arrays.asList("10", "zz").stream().
forEach((element) -> { out.println(converter.convertToInt(element)); });
public class StringConverter {
public int convertToInt(String value) throws Exception {
return Integer.parseInt(value);
}
}
StringConverter converter = new StringConverter();
Arrays.asList("10", "zz", "20").stream().
forEach((element) -> {
try {
out.println(converter.convertToInt(element));
} catch(Exception ex) {
throw new RuntimeException(ex);
}
});
try {
Arrays.asList("10", "z", "20", "c").stream()
.flatMap((element) -> {
try {
out.println(converter.convertToInt(element));
return null;
} catch (Exception ex) {
return Stream.of(new RuntimeException(ex));
}
})
.reduce((ex1, ex2) -> {
ex1.addSuppressed(ex2);
return ex1;
})
.ifPresent(ex -> {
throw ex;
});
} catch(Exception ex) {
ex.printStackTrace();
}
// Na podstawie: https://stackoverflow.com/questions/30117134/aggregate-runtime-exceptions-in-java-8-streams